
#include <BFont>
#include <BWidget>
#include "member_BMenu.h"
#include "member_BWidget.h"

using namespace BWE;

member_BMenu::member_BMenu(BMenu* menu)
{
	boss = menu;
	align = Align_LeftCenter;
	form = Form_IconText;
	arrowGraph = Graph_Arrow_Right;
	spacing = 1;
	separatorSize = 1;
	dirty = false;
	pressed = false;
	expanded = true;
}
member_BMenu::~member_BMenu()
{

}

void member_BMenu::raiseSignal(int signal, const BValue& value)
{
	BMenu* menu = boss;
	while (menu)
	{
		menu->emit(signal, value);
		menu->hide();
		menu = dynamic_cast<BMenu*>(widget_member(menu)->parent);
	}
}

BMenu* member_BMenu::locateMenu(const BString& path, BString& temp)
{
	if (path.contain('/'))
	{
		int pos = 0;
		int end = 0;
		end = path.find('/', pos);
		BMenu* menu = boss;
		while (end < path.size())
		{
			path.substr(temp, pos, end);
			menu = menu->menu(temp);
			if (!menu)
				return 0;
			pos = end + 1;
			end = path.find('/', pos);
		}
		path.substr(temp, pos, end);
		return menu;
	}
	return 0;
}

void member_BMenu::freshRects()
{
	if (!dirty)
		return;

	const BStyle* style = boss->realStyle();
	const BFont* font = boss->font();
	if (!font)
		return;

	int fsize = font->size();

	BSize realIconSize = iconSize;
	if (realIconSize.width() < 1)
		realIconSize.width() = fsize;
	if (realIconSize.height() < 1)
		realIconSize.height() = fsize;

	BSize realArrowSize = arrowSize;
	if (realArrowSize.width() < 1)
		realArrowSize.width() = fsize / 3;
	if (realArrowSize.height() < 1)
		realArrowSize.height() = fsize / 3;

	BMargin margin = boss->margin();
	BRect crect = boss->centerRect();
	int cx = crect.x();
	int cy = crect.y();

	int width = 0;
	int height = 0;
	int arrowSpace = bMax(realArrowSize.width(), fsize);
	for (int i = 0; i < items.size(); i++)
	{
		MenuItem& item = items[i];
		if (item.dirty)
		{
			item.ia_form = form;
			item.ia_align = align;
			item.ia_imageSize = realIconSize;
			item.ia_spacing = spacing;
			item.arrowRect = realArrowSize;
			if (item.empty())
				item.hsize = separatorSize;
			else
				item.freshSize(style, font);
			item.dirty = false;
		}
		width = bMax(width, item.hsize.width() + spacing + arrowSpace);
		height += item.hsize.height() + spacing;
	}
	height -= spacing;
	int posX = cx;
	int posY = cy;
	for (int i = 0; i < items.size(); i++)
	{
		MenuItem& item = items[i];
		item.adjustRect(posX, posY, crect.width(), item.hsize.height());
		BRect arrowArea = item.rect;
		arrowArea.left() = item.rect.right() - arrowSpace;
		item.arrowRect = arrowArea.align(Align_Center, realArrowSize);
		posY += item.hsize.height() + spacing;
	}
	conentSize.set(width, height);
	dirty = false;
}

void member_BMenu::slotActionTriggered(BObject* object, const BValue& value)
{
	BAction* action = (BAction*)object;
	raiseSignal(Signal_Triggered, action);
	//boss->setFocused(false);
}
void member_BMenu::slotActionRenamed(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].action == object)
		{
			dirty = true;
			items[i].namedIcon = 0;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
void member_BMenu::slotActionTextChanged(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].action == object)
		{
			dirty = true;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
void member_BMenu::slotActionIconChanged(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].action == object)
		{
			dirty = true;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
void member_BMenu::slotActionChecked(BObject* object, const BValue& value)
{
	BAction* action = (BAction*)object;
	boss->emit(Signal_Checked, action);
}

void member_BMenu::slotMenuRenamed(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].menu == object)
		{
			dirty = true;
			items[i].namedIcon = 0;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
void member_BMenu::slotMenuIconChanged(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].menu == object)
		{
			dirty = true;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
void member_BMenu::slotMenuTitleChanged(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].menu == object)
		{
			dirty = true;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
void member_BMenu::slotMenuStyleChanged(BObject* object, const BValue& value)
{
	for (int i = 0; i < items.size(); i++)
	{
		if (items[i].menu == object)
		{
			dirty = true;
			items[i].dirty = true;
			boss->fresh();
			break;
		}
	}
}
